package com.love.cloud.admin.service.impl;

import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.love.cloud.admin.api.entity.SysOauthClientDetails;
import com.love.cloud.admin.api.entity.SysUser;
import com.love.cloud.admin.api.vo.AuthVo;
import com.love.cloud.admin.config.properties.SosSecurityProperties;
import com.love.cloud.admin.mapper.SysOauthClientDetailsMapper;
import com.love.cloud.admin.mapper.SysUserMapper;
import com.love.cloud.admin.service.AuthService;
import com.love.cloud.admin.service.DingTalkService;
import com.love.cloud.auth.api.SosAuthProvider;
import com.love.cloud.common.core.config.SseEmitterServer;
import com.love.cloud.common.core.constant.CacheConstants;
import com.love.cloud.common.core.constant.SecurityConstants;
import com.love.cloud.common.core.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author hongdongqu
 */
@Service
public class AuthServiceImpl implements AuthService {
    @Resource
    private SysOauthClientDetailsMapper sysOauthClientDetailsMapper;
    @Resource
    private SosSecurityProperties sosSecurityProperties;
    @Resource
    private CacheManager cacheManager;
    @Resource
    private DingTalkService dingTalkService;
    @Resource
    private SysUserMapper sysUserMapper;

    @DubboReference(version = "1.0.0", timeout = 30000)
    private SosAuthProvider sosAuthProvider;



    @Override
    public Map<String, Object> getToken(HttpServletRequest request, AuthVo authVo) {
        QueryWrapper<SysOauthClientDetails> queryWrapper=new QueryWrapper<>();
        queryWrapper.lambda().eq(SysOauthClientDetails::getClientId,authVo.getClientId())
                .eq(SysOauthClientDetails::getClientSecret,authVo.getClientSecret());
        List<SysOauthClientDetails> sysOauthClientDetailsList = sysOauthClientDetailsMapper.selectList(queryWrapper);
        if(sysOauthClientDetailsList==null||sysOauthClientDetailsList.size()>1){
            throw new BusinessException("获取到客户端信息异常");
        }
        SysOauthClientDetails sysOauthClientDetails=sysOauthClientDetailsList.get(0);
        //如果配置放行地址为空就默认全部ip都可以访问
        if(StringUtils.isNotEmpty(sysOauthClientDetails.getAllowIp())){
            String clientIP = ServletUtil.getClientIP(request);
            boolean isPass=false;
            String[] split = sysOauthClientDetails.getAllowIp().split(",");
            for (String allowIp :split) {
                if(clientIP.equals(allowIp)){
                    isPass=true;
                    break;
                }
            }
            if(!isPass){
                throw new BusinessException("ip:"+clientIP+" 访问受限");
            }
        }
        Map<String, Object> paramMap=new HashMap<>();
        paramMap.put("client_id",authVo.getClientId());
        //客户端模式
        paramMap.put("grant_type",authVo.getType());
        paramMap.put("client_secret",authVo.getClientSecret());
        //处理特殊的业务逻辑
        switch (authVo.getType()){
            case SecurityConstants.GRANT_TYPE_CUSTOM_DING_ID:
                if(StringUtils.isEmpty(authVo.getDingAccountId())){
                    throw new BusinessException("请传入钉钉账户id");
                }
                paramMap.put("accountId",authVo.getDingAccountId());
                break;
            case SecurityConstants.GRANT_TYPE_PASSWORD:
                if(StringUtils.isEmpty(authVo.getUserName())){
                    throw new BusinessException("请传入用户名");
                }
                if(StringUtils.isEmpty(authVo.getPassword())){
                    throw new BusinessException("请传入密码");
                }
                paramMap.put("username",authVo.getUserName());
                paramMap.put("password",authVo.getPassword());
                break;
            case SecurityConstants.GRANT_TYPE_CUSTOM_PHONE_OPEN_CODE:
                if(StringUtils.isEmpty(authVo.getPhone())){
                    throw new BusinessException("请传入手机号");
                }
                if(StringUtils.isEmpty(authVo.getOpenId())){
                    throw new BusinessException("请传入openId");
                }
                paramMap.put("phone",authVo.getPhone());
                paramMap.put("openCode",authVo.getOpenId());
                break;
        }

        String json= HttpUtil.post(sosSecurityProperties.getOauthTokenUrl(), paramMap);
        JSONObject jsonObject = JSON.parseObject(json);
        //有code返回时说明为报错了
        if(jsonObject.get("code")!=null){
            throw new BusinessException(jsonObject.getString("msg"));
        }
        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("access_token",jsonObject.get("access_token"));
        resultMap.put("expires_in",jsonObject.get("expires_in"));
        return resultMap;
    }

    @Override
    public Object getTokenInfoByAccountId(HttpServletRequest request, AuthVo authVo) {
        if (StringUtils.isEmpty(authVo.getDingAccountId())) {
            throw new BusinessException("请传入浙政钉id");
        }
        //获取通过浙政钉获取到用户信息
        QueryWrapper<SysUser> queryWrapper=new QueryWrapper();
        queryWrapper.lambda().eq(SysUser::getZDingAccountId,authVo.getDingAccountId())
                .last(" limit 1 ");
        SysUser sysUser = sysUserMapper.selectOne(queryWrapper);
        if(sysUser==null){
            //执行添加用户逻辑
            dingTalkService.addUserByAccountId(authVo.getDingAccountId(),authVo.getEmployeeCode());
        }
        //调用登录接口token信息
        Map<String, Object> tokenInfo = this.getToken(request, authVo);
        return tokenInfo;
    }

    @Override
    public void clearAllUserTokenAndDetail() {
        //先删除用户详情的数据
        Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS);
        cache.clear();
        //清除token
        sosAuthProvider.removeAllAccessToken();
        //发送全部see客户端消息刷新token
        Map<String,Object> refreshMap=new HashMap<>();
        refreshMap.put("refreshToken",true);
        //广播全部在线用户
        SseEmitterServer.batchSendMessage(JSON.toJSONString(refreshMap));
    }
}
